package com.example.memento.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.Builder;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;

/**
 * 下载任务实体
 * 管理词典文件的下载任务状态
 */
@Table("download_tasks")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class DownloadTask {
    
    @Id(keyType = KeyType.Auto)
    private Long id;
    
    @NotBlank(message = "任务ID不能为空")
    @Size(max = 100, message = "任务ID长度不能超过100个字符")
    private String taskId;
    
    @NotBlank(message = "词典源名称不能为空")
    @Size(max = 100, message = "词典源名称长度不能超过100个字符")
    private String sourceName;
    
    @NotBlank(message = "下载URL不能为空")
    @Size(max = 500, message = "下载URL长度不能超过500个字符")
    private String url;
    
    @NotNull(message = "任务状态不能为空")
    private TaskStatus status;
    
    @Builder.Default
    private Long downloadedBytes = 0L;
    
    @Builder.Default
    private Long totalBytes = 0L;
    
    @Size(max = 1000, message = "错误信息长度不能超过1000个字符")
    private String errorMessage;
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime startTime;
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime endTime;
    
    @Size(max = 500, message = "本地路径长度不能超过500个字符")
    private String localPath;
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createdAt;
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updatedAt;
    
    /**
     * 任务状态枚举
     */
    public enum TaskStatus {
        PENDING("等待中"),
        DOWNLOADING("下载中"),
        COMPLETED("已完成"),
        FAILED("失败"),
        CANCELLED("已取消");
        
        private final String description;
        
        TaskStatus(String description) {
            this.description = description;
        }
        
        public String getDescription() {
            return description;
        }
    }
    
    /**
     * 设置创建时间戳
     * 在MyBatis-Flex中，我们需要手动调用此方法
     */
    public void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
        if (startTime == null) {
            startTime = LocalDateTime.now();
        }
    }
    
    /**
     * 设置更新时间戳
     * 在MyBatis-Flex中，我们需要手动调用此方法
     */
    public void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
    
    /**
     * 计算下载进度百分比
     */
    public double getProgressPercentage() {
        if (totalBytes == null || totalBytes == 0) {
            return 0.0;
        }
        return (downloadedBytes != null ? downloadedBytes : 0) * 100.0 / totalBytes;
    }
    
    /**
     * 检查任务是否完成
     */
    public boolean isCompleted() {
        return status == TaskStatus.COMPLETED;
    }
    
    /**
     * 检查任务是否失败
     */
    public boolean isFailed() {
        return status == TaskStatus.FAILED;
    }
    
    /**
     * 检查任务是否进行中
     */
    public boolean isInProgress() {
        return status == TaskStatus.DOWNLOADING;
    }
    
    /**
     * 获取任务持续时间（秒）
     */
    public Long getDurationSeconds() {
        if (startTime == null) {
            return 0L;
        }
        
        LocalDateTime end = endTime != null ? endTime : LocalDateTime.now();
        return java.time.Duration.between(startTime, end).getSeconds();
    }
    
    /**
     * 获取下载速度（字节/秒）
     */
    public Long getDownloadSpeed() {
        Long duration = getDurationSeconds();
        if (duration == null || duration == 0 || downloadedBytes == null) {
            return 0L;
        }
        return downloadedBytes / duration;
    }
    
    /**
     * 获取格式化的下载速度
     */
    public String getFormattedDownloadSpeed() {
        Long speed = getDownloadSpeed();
        if (speed == null || speed == 0) {
            return "0 B/s";
        }
        
        if (speed < 1024) {
            return speed + " B/s";
        } else if (speed < 1024 * 1024) {
            return String.format("%.1f KB/s", speed / 1024.0);
        } else {
            return String.format("%.1f MB/s", speed / (1024.0 * 1024.0));
        }
    }
}
